package com.micai.boss.base.utils;

import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;

/**
 * @desc webservice发送请求工具类
 * @author zhaoxinguo
 *
 */
public class WebServiceUtils {
	
	public static int socketTimeout = 30000;// 请求超时时间
	public static int connectTimeout = 30000;// 传输超时时间
	public static Logger logger = LoggerFactory.getLogger(WebServiceUtils.class);
	
	/**
	 * 方法一：使用SOAP发送消息（HttpClient方式）
	 * @param soapUrl
	 * @param soapXml
	 * @param soapAction
	 * @return
	 */
	public static String doPostSoap(String soapUrl, String soapXml, String soapAction) {
		String retStr = "";
		// 创建HttpClientBuilder
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
		// HttpClient
		CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
		HttpPost httpPost = new HttpPost(soapUrl);
		// 设置请求和传输超时时间
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		httpPost.setConfig(requestConfig);
		try {
			httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
			httpPost.setHeader("SOAPAction", soapAction);
			StringEntity data = new StringEntity(soapXml, Charset.forName("UTF-8"));
			httpPost.setEntity(data);
			CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
			HttpEntity httpEntity = response.getEntity();
			if (httpEntity != null) {
				// 打印响应内容
				retStr = EntityUtils.toString(httpEntity, "UTF-8");
				logger.info("response:" + retStr);
			}
			// 释放资源
			closeableHttpClient.close();
		} catch (Exception e) {
			logger.error("请求出错！", e);
		}
		return retStr;
	}
	
	/**
	 * 方法二：使用SOAP1.1发送消息
	 * 
	 * @param soapUrl
	 * @param soapXml
	 * @param soapAction
	 * @return
	 */
	public static String doPostSoap1_1(String soapUrl, String soapXml, String soapAction) {
		String retStr = "";
		// 创建HttpClientBuilder
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
		// HttpClient
		CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
		HttpPost httpPost = new HttpPost(soapUrl);
		// 设置请求和传输超时时间
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		httpPost.setConfig(requestConfig);
		try {
			httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
			httpPost.setHeader("SOAPAction", soapAction);
			StringEntity data = new StringEntity(soapXml, Charset.forName("UTF-8"));
			httpPost.setEntity(data);
			CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
			HttpEntity httpEntity = response.getEntity();
			if (httpEntity != null) {
				// 打印响应内容
				retStr = EntityUtils.toString(httpEntity, "UTF-8");
				logger.info("response:" + retStr);
			}
			// 释放资源
			closeableHttpClient.close();
		} catch (Exception e) {
			logger.error("exception in doPostSoap1_1", e);
		}
		return retStr;
	}
	
	/**
	 * 方法三：使用SOAP1.2发送消息
	 * 
	 * @param soapUrl
	 * @param soapXml
	 * @param soapAction
	 * @return
	 */
	public static String doPostSoap1_2(String soapUrl, String soapXml, String soapAction) {
		String retStr = "";
		// 创建HttpClientBuilder
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
		// HttpClient
		CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
		HttpPost httpPost = new HttpPost(soapUrl);
		// 设置请求和传输超时时间
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
		httpPost.setConfig(requestConfig);
		try {
			httpPost.setHeader("Content-Type", "application/soap+xml;charset=UTF-8");
			httpPost.setHeader("SOAPAction", soapAction);
			StringEntity data = new StringEntity(soapXml, Charset.forName("UTF-8"));
			httpPost.setEntity(data);
			CloseableHttpResponse response = closeableHttpClient.execute(httpPost);
			HttpEntity httpEntity = response.getEntity();
			if (httpEntity != null) {
				// 打印响应内容
				retStr = EntityUtils.toString(httpEntity, "UTF-8");
				logger.info("response:" + retStr);
			}
			// 释放资源
			closeableHttpClient.close();
		} catch (Exception e) {
			logger.error("exception in doPostSoap1_2", e);
		}
		return retStr;
	}
	
	/**
	 * 方法四：使用HttpURLConnection方式连接
	 * @param soapUrl
	 * @param soapXML
	 * @return
	 * @throws IOException
	 */
	public static String httpURLConnection(String soapUrl, String soapXML) throws IOException {
		String state = "";
		HttpURLConnection connection = null;
		try {
			// 第一步：创建服务地址
			// http://127.0.0.1:8080/PeopleSoftService/getPerson.wsdl
			URL url = new URL(soapUrl);
			// 第二步：打开一个通向服务地址的连接
			connection = (HttpURLConnection) url.openConnection();
			// 第三步：设置参数
			// 3.1发送方式设置：POST必须大写
			connection.setRequestMethod("POST");
			// 3.2设置数据格式：content-type
			connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
			// 3.3设置输入输出，因为默认新创建的connection没有读写权限，
			connection.setDoInput(true);
			connection.setDoOutput(true);
			// 第四步：组织SOAP数据，发送请求
			// 将信息以流的方式发送出去
			OutputStream os = connection.getOutputStream();
			os.write(soapXML.getBytes("utf-8"));
			// 第五步：接收服务端响应，打印
			int responseCode = connection.getResponseCode();
			logger.info("responseCode:" + responseCode);
			if (200 == responseCode) {
				InputStream is = connection.getInputStream();
				StringBuffer sb = new StringBuffer();
				String readLine = new String();
				BufferedReader responseReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
				while ((readLine = responseReader.readLine()) != null) {
					sb.append(readLine).append("\n");
				}
				responseReader.close();
				state = sb.toString();
				logger.info("state:" + state);
				if (state.contains("OK")) {
					state = "0";
				}
				is.close();
			}
			os.close();
		} catch (Exception e) {
			state = "-1";
			if (logger.isErrorEnabled()) {
				logger.error("短信发送失败:{}", e);
			}
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}
		return state;
	}
	
	/**
	 * 组装入参xml
	 * @return
	 */
	public static String getXML(){
	  // TODO 这里待优化，可以弄成动态参数
	  String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
	      "<SMS type=\"send\">"+
	       "<Message SmsID=\"20130308094612321123\" SendNum=\"100\" RecvNum=\"18611966723\" Content=\"发送短信内容555\"/>" +
	      "</SMS>";
	  return xml;
	}
	
	/**
	 * 组装soapXml
	 * @param loginId
	 * @param pwd
	 * @return
	 */
	public static String getSoapXML(String loginId, String pwd){
	  String xml = getXML();
	  xml = xml.replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("'", "&apos;").replaceAll("\"", "&quot;");
	  String soapXML = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://webservice.sms.api.poweru.cn/\">\n" +
	    "   <soapenv:Header/>\n" +
	    "   <soapenv:Body>\n" +
	    "      <ser:AddSMSList>\n" +
	    "         <loginId>" + loginId + "</loginId>\n" +
	    "         <passWord>" + pwd + "</passWord>\n" +
	    "         <XML>" + xml + "</XML>\n" +
	    "      </ser:AddSMSList>\n" +
	    "   </soapenv:Body>\n" +
	    "</soapenv:Envelope>";
	  return soapXML;
	}
	
	public static void main(String[] args) throws IOException {
		String soapUrl = "http://172.18.3.243:8080/SMSG/services/SMS";
		String loginId = "admin";
		String pwd = "123456";
		// 方法一
		/*String response = doPostSoap(soapUrl, getSoapXML(loginId, pwd), null);*/
		// 方法二
		/*String response = doPostSoap1_1(soapUrl, getSoapXML(loginId, pwd), null);*/
		// 方法三
		/*String response = doPostSoap1_2(soapUrl, getSoapXML(loginId, pwd), null);*/
		// 方法四
		String response = httpURLConnection(soapUrl, getSoapXML(loginId, pwd));
		logger.info("response:" + response);
	}

}
